package com.ioidea.ble

import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCharacteristic
import cn.com.heaton.blelibrary.ble.Ble
import cn.com.heaton.blelibrary.ble.BleRssiDevice
import cn.com.heaton.blelibrary.ble.callback.BleConnectCallback
import cn.com.heaton.blelibrary.ble.callback.BleNotifyCallback
import cn.com.heaton.blelibrary.ble.callback.BleWriteCallback
import cn.com.heaton.blelibrary.ble.model.BleDevice
import cn.com.heaton.blelibrary.ble.queue.RequestTask
import com.ioidea.base.util.MyLogger
import com.ioidea.base.util.ReportDataLogger
import com.ioidea.ble.bean.BleRequest
import com.ioidea.ble.bean.BleResponse
import com.ioidea.ble.bean.EnumResponse
import com.ioidea.ble.en.EnumBleStatus
import com.ioidea.ble.proto.ProtoBase
import java.nio.charset.StandardCharsets
import java.util.UUID
import java.util.concurrent.atomic.AtomicBoolean

/**
 * 蓝牙的管理
 * 负责蓝牙的连接 notify status
 * 特点:write数据 不是从write回来的是通过 notify回来的
 */


 open class BLeController: BleThreadQueue() {


    //核心类对蓝牙提供操作接口
    val mBle: Ble<BleRssiDevice> = Ble.getInstance<BleRssiDevice>()

    //已经连接上的设备  后面想连上的设备直接取连
    var mConnectedBle: BleRssiDevice? = null

    //特征值对象
    var mBluetoothGattCharacteristic: BluetoothGattCharacteristic? = null

    //蓝牙状态回调
    lateinit var bleStatusListener: (enumBleStatus: EnumBleStatus) -> Unit

    //一发多回数据
    lateinit var deviceGroupIdListener: (data: ByteArray) -> Unit
    //主动上报数据
    lateinit var reportDataListener: (data: ByteArray) -> Unit

    var mState = EnumBleStatus.NOT_CONNECTED


    var retryConnectCount=0
    companion object{
        //重试最大次数
        const val MAX_RETRY_COUNT=3
    }

    private val looping: AtomicBoolean = AtomicBoolean(true)

    init {
        mBle.setBleStatusCallback { isOn ->
            MyLogger.hLog().e("蓝牙 开关：$isOn")
            if (isOn) {
                updateState(EnumBleStatus.ABLE)
//                if (mConnectedBle!=null){
//                    retryConnectCount=0
//                    mBle.connect(mConnectedBle, connectCallback)
//                }
            } else {
                updateState(EnumBleStatus.DISABLE)
                if (mConnectedBle!=null){
                    disconnect(mConnectedBle!!)
                }

            }
        }

    }

    val connectCallback: BleConnectCallback<BleRssiDevice> =
        object : BleConnectCallback<BleRssiDevice>() {
            override fun onConnectionChanged(device: BleRssiDevice) {
                if (device.isConnected) {
                    updateState(EnumBleStatus.CONNECTED)
                    MyLogger.hLog().i("已连接")

                    setDeviceSn(device)

                    mConnectedBle = device
                } else if (device.isConnecting) {
                    updateState(EnumBleStatus.CONNECTING)
                    MyLogger.hLog().i("连接中...")
                } else if (device.isDisconnected) {
                    updateState(EnumBleStatus.NOT_CONNECTED)
                    MyLogger.hLog().i("未连接")
                    if (retryConnectCount<MAX_RETRY_COUNT){
                        mBle.connect(device, this)
                        MyLogger.hLog().e("重连：$retryConnectCount")
                        retryConnectCount++
                    }
                }
            }

            override fun onConnectFailed(device: BleRssiDevice, errorCode: Int) {
                super.onConnectFailed(device, errorCode)
                updateState(EnumBleStatus.NOT_CONNECTED)
            }

            override fun onConnectCancel(device: BleRssiDevice) {
                super.onConnectCancel(device)
                updateState(EnumBleStatus.NOT_CONNECTED)
                MyLogger.hLog().e("onConnectCancel: " + device.bleName)
            }

            override fun onServicesDiscovered(device: BleRssiDevice, gatt: BluetoothGatt) {
                super.onServicesDiscovered(device, gatt)
                val services = gatt.services
                //获取指定服务
                val characteristic = services[2]
                val characteristics = characteristic.characteristics
                for (bluetoothGattCharacteristic in characteristics) {
                    val charaProp = bluetoothGattCharacteristic.properties
                    if (charaProp and BluetoothGattCharacteristic.PROPERTY_WRITE != 0) {
                        mBluetoothGattCharacteristic = bluetoothGattCharacteristic
                    } else if (charaProp and BluetoothGattCharacteristic.PROPERTY_NOTIFY != 0) {
                        notifyBle(device, bluetoothGattCharacteristic)
                    }
                }
            }

            override fun onReady(device: BleRssiDevice) {
                super.onReady(device)
            }
        }

    private fun setDeviceSn(device: BleRssiDevice) {
        val bleName: String = device.bleName
        val s = bleName.split(" ".toRegex()).dropLastWhile { it.isEmpty() }
            .toTypedArray()
        if (s.size == 3) {
            val currentSn = s[2]
            device.sn = currentSn
        }
        for (s1 in s) {
            MyLogger.hLog().i("name:$s1")
        }

    }


    fun updateState(enumBleStatus: EnumBleStatus) {
        bleStatusListener(enumBleStatus)
    }

    open fun notifyBle(device: BleDevice, characteristic: BluetoothGattCharacteristic) {
        MyLogger.hLog().i("notifyBle 创建回调")


        Ble.getInstance<BleDevice>().enableNotifyByUuid(
            device,
            true,
            characteristic.service.uuid,
            characteristic.uuid,
            object : BleNotifyCallback<BleDevice>() {
                override fun onChanged(
                    device: BleDevice,
                    characteristic: BluetoothGattCharacteristic
                ) {
                    MyLogger.hLog().e("characteristic.service.uuid:"+characteristic.service.uuid)
                    MyLogger.hLog().e("characteristic.uuid:"+characteristic.uuid)
                    val msg = String(characteristic.value, StandardCharsets.UTF_8)

                    //这里要处理STA 上报的数据
                    if (msg.contains(ProtoBase.REPORT_DATA_CONTENT)) {
                        ReportDataLogger.hLog().i("收到数据成功 <============$msg")
                        reportDataListener(characteristic.value)
                    }else if (msg.contains(ProtoBase.GROUP_CONTENT)){
                        deviceGroupIdListener(characteristic.value)
                        signal(characteristic.value)
                    } else {
                        MyLogger.hLog().i("收到数据成功 <============ $msg")
                        receive(characteristic.value)
                    }

                }

                override fun onNotifySuccess(device: BleDevice) {
                    super.onNotifySuccess(device)
                    //启用通知
                    MyLogger.hLog().i("收到数据回调 ============> Notifications_enabled")
                    updateState(EnumBleStatus.SUCCESS)
                }

                override fun onNotifyCanceled(device: BleDevice) {
                    super.onNotifyCanceled(device)
                    MyLogger.hLog()
                        .i("收到数据回调 ============> Notifications and indications disabled")
                }


            })
    }


    @Synchronized
    open fun receive(data: ByteArray) {
        //唤醒锁发送数据
        signal(data)
    }




    override fun sendRequest(request: BleRequest) {
        if (mConnectedBle == null || mBluetoothGattCharacteristic == null) {
            request.callback(BleResponse(EnumResponse.ERROR))
            return
        }
        val serviceUUID = mBluetoothGattCharacteristic!!.service.uuid
        val characteristicUUID = mBluetoothGattCharacteristic!!.uuid
        val sendRequestTxt= String(request.sendDataArray,StandardCharsets.US_ASCII)

        MyLogger.hLog().e("sendRequest.service.uuid:"+serviceUUID)
        MyLogger.hLog().e("sendRequest.characteristicUUID:"+characteristicUUID)
        MyLogger.hLog().e("=====>sendRequestTxt:${sendRequestTxt}")

        MyLogger.hLog().e("=====>sendRequestTxt:${request.sendDataArray.joinToString (", ")}")
        writeByUuid(
            mConnectedBle!!,
            request.sendDataArray,
            serviceUUID,
            characteristicUUID,
            object : BleWriteCallback<BleRssiDevice>() {
                override fun onWriteSuccess(
                    device: BleRssiDevice,
                    characteristic: BluetoothGattCharacteristic
                ) {
                    MyLogger.hLog().d("onWriteSuccess1 ============>")
//                    addTimeout()
//                    request.callback(BleResponse(EnumResponse.WRITE_SUCC))
                }

                override fun onWriteFailed(device: BleRssiDevice, failedCode: Int) {
                    super.onWriteFailed(device, failedCode)
//                    notifyCallBack.notify(ByteArray(0))
                    request.callback(BleResponse(EnumResponse.WRITE_FAIL))
                    MyLogger.hLog().d("w发送数据失败 ============> $failedCode")
                }
            })

    }


    /**
     * 只用写 不用回
     */
    open fun writeDataToQueue(dataStr: String) {
        MyLogger.hLog().e("dataStr:$dataStr")

        val requestTask = RequestTask.Builder()
            .devices(mConnectedBle)
            .delay(0)
            .data(dataStr.toByteArray())
            .build()
        mBle.writeQueue(requestTask)
    }

    open fun writeByUuid(
        mBleDevice: BleRssiDevice,
        bytes: ByteArray,
        serviceUUID: UUID,
        characteristicUUID: UUID,
        bleWriteCallback: BleWriteCallback<BleRssiDevice>
    ) {
        //通过特定服务和特征值uuid写入数据
        mBle.writeByUuid(mBleDevice, bytes, serviceUUID, characteristicUUID, bleWriteCallback)
    }

    /**
     * 蓝牙断开连接
     */
    fun disconnect(device: BleRssiDevice) {
        mBle.cancelCallback(connectCallback)
        mBle.disconnect(device)
    }

}